package com.yixia.web.controller.system;

import com.yixia.common.core.domain.entity.SysArea;
import com.yixia.common.utils.page.TableDataInfo;
import com.yixia.common.utils.poi.ExcelUtil;
import com.yixia.system.domain.system.SysPost;
import com.yixia.common.core.domain.entity.SysDept;
import com.yixia.common.core.domain.entity.SysRole;
import com.yixia.common.core.domain.entity.SysUser;
import com.yixia.common.enums.BusinessType;
import com.yixia.common.utils.DateUtil;
import com.yixia.common.utils.SecurityUtils;
import com.yixia.common.utils.StringUtils;
import com.yixia.common.config.YiXiaConfig;
import com.yixia.common.core.controller.BaseController;

import com.yixia.common.core.domain.AjaxResult;
import com.yixia.common.core.domain.TreeSelect;
import com.yixia.common.annotation.Log;

import com.yixia.common.utils.page.PageBean;

import com.yixia.system.service.system.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 用户管理
 */
@Api(tags = "用户管理模块")
@Slf4j
@RestController
@RequestMapping("/system/user")
public class SysUserController extends BaseController {

    @Autowired
    private SysUserService userService;

    @Autowired
    private BCryptPasswordEncoder bcryptPasswordEncoder;


    @Autowired
    private SysRoleService roleService;

    @Autowired
    private SysAreaService sysAreaService;

    @Autowired
    private SysDeptService deptService;

    @Autowired
    private SysPostService postService;

    /**
     * 修改密码
     *
     * @param sysUser
     * @return
     */
    @ApiOperation("修改密码")
    @PostMapping("/updateUserPwd")
    @PreAuthorize("hasAuthority('system:user:resetPwd')")
    public AjaxResult updateUserPwd(@RequestBody SysUser sysUser) {

        /*先在数据库中查出旧密码*/
        SysUser currentUser = userService.getById(sysUser.getUserId());
        /*旧密码与新密码之间作比较*/
        if (bcryptPasswordEncoder.matches(sysUser.getOldPassword(), currentUser.getPassword())) {
            /*比对成功就将密码进行修改*/
            /*对新密码进行加密*/
            currentUser.setPassword(bcryptPasswordEncoder.encode(sysUser.getNewPassword()));
            currentUser.setUpdateTime(new Date());
            userService.updateById(currentUser);
            return AjaxResult.success("密码修改成功！");
        }
        return AjaxResult.error("旧密码输入错误，密码修改失败！");
    }


    /**
     * 重置密码
     * 根据用户id将密码进行重置
     * 1. 校验用户是否允许操作
     * 2. 校验用户是否有数据权限
     *
     * @param sysUser
     * @return
     */
    @PostMapping("/resetPwd")
    //@PreAuthorize("hasAuthority('system:user:resetPwd')")
    public AjaxResult resetPwd(@RequestBody SysUser sysUser) {
        log.info("编号为{}的用户 重置密码...", sysUser.getUserId());
        /*校验用户是否允许操作，不是超级管理员就可以操作*/
        userService.checkUserAllowed(sysUser);
        /*校验用户是否有数据权限*/
        userService.checkUserDataScope(sysUser.getUserId());
        /*满足上面的条件就开始修改*/
        if (StringUtils.isNotEmpty(sysUser.getNewPassword())) {
            /*对密码进行加密*/
            sysUser.setPassword(SecurityUtils.encryptPassword(sysUser.getNewPassword()));
        }
        /*修改*/
        return toAjax(userService.resetPwd(sysUser));
    }


    /**
     * 上传用户头像图片
     *
     * @param file
     * @return
     * @throws Exception
     */
    @RequestMapping("/uploadAvatar")
    @PreAuthorize("@yixia.hasPermi('system:user:edit')")
    public Map<String, Object> uploadAvatar(MultipartFile file) throws Exception {
        Map<String, Object> resultMap = new HashMap<>();
        if (!file.isEmpty()) {
            // 获取文件名
            String filePath = YiXiaConfig.getAvatarPath();
            String originalFilename = file.getOriginalFilename();
            String suffixName = originalFilename.substring(originalFilename.lastIndexOf("."));
            String newFileName = DateUtil.getCurrentDateStr() + suffixName;
            FileUtils.copyInputStreamToFile(file.getInputStream(), new File(filePath + newFileName));
            resultMap.put("code", 0);
            resultMap.put("msg", "上传成功");
            Map<String, Object> dataMap = new HashMap<>();
            dataMap.put("title", newFileName);
            dataMap.put("src", "userAvatar/" + newFileName);
            resultMap.put("data", dataMap);
        }
        return resultMap;
    }


    /**
     * 修改用户头像
     *
     * @param sysUser
     * @return
     */
    @RequestMapping("/updateAvatar")
    @PreAuthorize("hasAuthority('system:user:edit')")
    public AjaxResult updateAvatar(@RequestBody SysUser sysUser) {
        SysUser currentUser = userService.getById(sysUser.getUserId());
        currentUser.setUpdateTime(new Date());
        currentUser.setAvatar(sysUser.getAvatar());
        userService.updateById(currentUser);
        return AjaxResult.success();
    }


    /**
     * COMMIT : 已完成
     * 根据条件分页查询用户信息
     */
    @ApiOperation("分页查询")
    @GetMapping("/list")
    @PreAuthorize("@yixia.hasPermi('system:user:query')")
    public TableDataInfo list(SysUser sysUser) {
        /*1. 获取分页信息*/
        startPageByHelper();
        /*2. 进行分页查询--返回的是page的数据集合*/
        List<SysUser> list = userService.selectUserPageList(sysUser);
        return getDataTable(list);
    }


    /**
     * COMMIT : 已完成
     * 添加用户
     */
    @ApiOperation("添加用户")
    @PostMapping("/add")
    @PreAuthorize("@yixia.hasPermi('system:user:add')")
    @Log(title = "用户管理->添加用户", businessType = BusinessType.INSERT)
    public AjaxResult add(@Validated @RequestBody SysUser user) {
        if (!userService.checkUserNameUnique(user)) {
            return error("新增用户'" + user.getUsername() + "'失败，登录账号已存在");
        } else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) {
            return error("新增用户'" + user.getUsername() + "'失败，手机号码已存在");
        } else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) {
            return error("新增用户'" + user.getUsername() + "'失败，邮箱账号已存在");
        }
        user.setPassword(bcryptPasswordEncoder.encode(user.getPassword()));
        userService.insertUser(user);
        return AjaxResult.success("添加成功！");
    }


    /**
     * COMMIT : 已完成
     * 修改用户
     */
    @ApiOperation("修改用户")
    @PutMapping("/edit")
    @Log(title = "用户管理->修改用户", businessType = BusinessType.UPDATE)
    @PreAuthorize("@yixia.hasPermi('system:user:edit')")
    public AjaxResult edit(@Validated @RequestBody SysUser user) {
        userService.checkUserAllowed(user);/*验证该用户是否允许操作*/
        userService.checkUserDataScope(user.getUserId());/*验证该userId是否有数据权限*/
        if (!userService.checkUserNameUnique(user)) {
            return error("修改用户'" + user.getUsername() + "'失败，登录账号已存在");
        } else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) {
            return error("修改用户'" + user.getUsername() + "'失败，手机号码已存在");
        } else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) {
            return error("修改用户'" + user.getUsername() + "'失败，邮箱账号已存在");
        }
        /*4. 对数据进行修改*/
        userService.updateUser(user);
        return AjaxResult.success("修改成功");
    }

    /**
     * COMMIT : 已完成
     * 删除用户
     */
    @ApiOperation("删除用户")
    @DeleteMapping("/delete/{userIds}")
    @Log(title = "用户管理->删除用户", businessType = BusinessType.DELETE)
    @PreAuthorize("@yixia.hasPermi('system:user:remove')")
    public AjaxResult delete(@PathVariable Long[] userIds) {
        if (ArrayUtils.contains(userIds, getUserId())) {
            return error("当前用户不能删除");
        }
        return toAjax(userService.deleteUserByIds(userIds));
    }


    /**
     * COMMIT : 已完成
     * 导出用户
     */
    @ApiOperation("导出用户")
    @PostMapping("/export")
    @Log(title = "用户管理->导出用户", businessType = BusinessType.EXPORT)
    @PreAuthorize("@yixia.hasPermi('system:user:export')")
    public void export(HttpServletResponse response, SysUser user) {
        /*将用户信息查找出来*/
        List<SysUser> list = userService.selectUserList(user);
        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
        util.exportExcel(response, list, "用户数据");
    }

    /**
     * COMMIT : 已完成
     * 用户导入
     */
    @ApiOperation("导入用户")
    @Log(title = "用户管理", businessType = BusinessType.IMPORT)
    @PreAuthorize("@yixia.hasPermi('system:user:import')")
    @PostMapping("/importData")
    public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception {
        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
        List<SysUser> userList = util.importExcel(file.getInputStream());
        String operName = getUsername();
        String message = userService.importUser(userList, updateSupport, operName);
        return success(message);
    }

    /**
     * COMMIT : 已完成
     * 下载上传模板
     */
    @ApiOperation("下载模板")
    @PostMapping("/importTemplate")
    public void importTemplate(HttpServletResponse response) {
        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
        util.importTemplateExcel(response, "用户数据");
    }


    /**
     * COMMIT : 已完成
     * 状态修改
     */
    @ApiOperation("状态修改")
    @PreAuthorize("@yixia.hasPermi('system:user:edit')")
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @PutMapping("/changeStatus")
    public AjaxResult changeStatus(@RequestBody SysUser user) {
        userService.checkUserAllowed(user);
        userService.checkUserDataScope(user.getUserId());
        return toAjax(userService.updateUserStatus(user));
    }

    /**
     * 查询是否可以更改用户名
     */
    @PostMapping("/checkUserName")
    public AjaxResult checkUserName(@RequestBody SysUser sysUser) {
        SysUser byUsername = userService.getByUsername(sysUser.getUsername());
        if (byUsername == null) {
            return AjaxResult.success();
        }
        return AjaxResult.error();
    }




    /**
     * 根据用户编号获取详细信息
     */
    @GetMapping(value = {"/", "/{userId}"})
    @ApiOperation("根据用户编号获取用户详细信息")
    @PreAuthorize("@yixia.hasPermi('system:user:query')")
    public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId) {
        log.info("根据用户编号获取详细信息:" + userId);
        /*1. 判断该userId是否存在，也就是是否有数据权限*/
        /*2. 查询出所有角色信息---布包扣超级管理员角色*/
        /*3. 查询出全部的岗位信息*/
        /*3. 查询出所有部门信息*/
        /*4. 如果传进来的Id不为空，则可以查询userId的信息*/
        /*5. 将上面的查询结果封装成对象进行返回*/
        if (StringUtils.isNotNull(userId)) {
            userService.checkUserDataScope(userId);
        }
        AjaxResult ajax = AjaxResult.success();
        List<SysRole> roles = roleService.selectRoleAll();
        ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
        List<SysPost> posts = postService.selectPostAll();
        ajax.put("posts", posts);
        List<SysDept> depts = deptService.selectDeptList(new SysDept());
        ajax.put("depts", depts);
        if (StringUtils.isNotNull(userId)) {
            SysUser user = userService.selectUserById(userId);
            ajax.put(AjaxResult.DATA_TAG, user);
            ajax.put("postIds", postService.selectPostIdsByUserId(userId));
            ajax.put("roleIds", user.getRoleList().stream().map(SysRole::getRoleId).collect(Collectors.toList()));
        }
        return ajax;
    }


    /**
     * 根据用户编号获取授权的角色
     *
     * @param userId
     * @return
     */
    @GetMapping("/authRole/list/{userId}")
    public AjaxResult authRole(@PathVariable("userId") Long userId) {
        AjaxResult ajax = AjaxResult.success();
        SysUser user = userService.selectUserById(userId);
        List<SysRole> roles = roleService.selectAllRolesOnAuthRoleByUserId(userId);
        ajax.put("user", user);
        ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
        return ajax;
    }

    /**
     * 根据用户编号获取授权的角色
     */
    @PutMapping("/authRole/add")
    public AjaxResult insertAuthRole(Long userId, Long[] roleIds) {
        /*判断该角色有没有数据权限*/
        userService.checkUserDataScope(userId);
        /*将角色数据进行插入*/
        userService.insertUserAuth(userId, roleIds);
        return success();
    }


    /**
     * 获取地域下拉树，权限'system:user:list'
     */
    @GetMapping("/areaTree")
    public AjaxResult getAreaTreeSelect(SysArea area) {
        List<TreeSelect> treeSelects = sysAreaService.selectAreaTreeList(area);
        /*树查出来后将其放到redis中*/
        return AjaxResult.success(treeSelects);
    }


    @GetMapping("/deptTree")
    @ApiOperation("获取部门树")
    @PreAuthorize("@yixia.hasPermi('system:user:list')")
    /* @PreAuthorize("yixia.hasPermi('system:user:list')")*/
    public AjaxResult deptTree(SysDept dept) {
        return success(deptService.selectDeptTreeList(dept));
    }

}
